package com.company.cloud.product.client;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.company.cloud.common.bean.BaseClientResult;
import com.company.cloud.common.constant.BaseConstant.YNEnum;
import com.company.cloud.common.data.bean.DataQueryRuleItem;
import com.company.cloud.common.utils.CheckUtils;
import com.company.cloud.product.modules.api.request.ProductQuery4PageRequest;
import com.company.cloud.product.modules.api.request.ProductQueryRequest;
import com.company.cloud.product.modules.api.response.Product;
import com.company.cloud.product.modules.api.response.ProductQuery4PageResponse;
import com.company.cloud.product.modules.api.response.ProductSimple;
import com.company.cloud.product.modules.api.response.Sku;
import com.company.cloud.product.modules.api.service.ProductRemoteService;
import com.company.cloud.product.modules.base.entity.ProductInfo;
import com.company.cloud.product.modules.base.service.ProductInfoService;
import com.company.cloud.product.modules.cache.service.ProductInfoCacheService;
import com.company.cloud.product.modules.cache.utils.ProductCacheConvertUtils;

import cn.hutool.core.util.StrUtil;
import lombok.extern.log4j.Log4j2;

@Log4j2
@RestController
@Service
public class ProductRemoteServiceImpl implements ProductRemoteService {

	@Autowired
	private ProductInfoCacheService productInfoCacheService;

	@Autowired
	private ProductInfoService productInfoService;

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Product> getProductById(String productNo) {
		if (StrUtil.isEmpty(productNo)) {
			return BaseClientResult.error();
		}
		try {
			Product product=productInfoCacheService.getProductByNoByCache(productNo);
			return BaseClientResult.success(product);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Product> getProductByDbById(String productNo) {
		if (StrUtil.isEmpty(productNo)) {
			return BaseClientResult.error();
		}
		try {
			Product product= productInfoCacheService.getProductByNoByDB(productNo);
			return BaseClientResult.success(product);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, Product>> getProductMapByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			Map<String, Product> data= productInfoCacheService.getProductMapByCache(productNos);
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, Product>> getProductMapByDbByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			Map<String, Product> data=productInfoCacheService.getProductMapByDB(productNos);
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<List<Product>> getProductListByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			List<Product> data= productInfoCacheService.getProductListByCache(productNos);
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<List<Product>> getProductListByDbByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			List<Product> data=productInfoCacheService.getProductListByDB(productNos);
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<ProductSimple> getProductSimpleById(String productNo) {
		if (StrUtil.isEmpty(productNo)) {
			return BaseClientResult.error();
		}
		try {
			Product product=productInfoCacheService.getProductByNoByCache(productNo);
			if(product==null) {
				return BaseClientResult.error();
			}
			return BaseClientResult.success(new ProductSimple(product));
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<ProductSimple> getProductSimpleByDbById(String productNo) {
		if (StrUtil.isEmpty(productNo)) {
			return BaseClientResult.error();
		}
		try {	
			Product product= productInfoCacheService.getProductByNoByDB(productNo);
			if(product==null) {
				return BaseClientResult.error();
			}
			return BaseClientResult.success(new ProductSimple(product));
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, ProductSimple>> getProductSimpleMapByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		
		try {
			Map<String, Product> productMap=productInfoCacheService.getProductMapByCache(productNos);
			if (CollectionUtils.isEmpty(productMap)) {
				return BaseClientResult.success();
			}
			Map<String, ProductSimple> data=new HashMap<String, ProductSimple>();
			for (Map.Entry<String, Product> item : productMap.entrySet()) {
				data.put(item.getKey(), new ProductSimple(item.getValue()));
			}
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, ProductSimple>> getProductSimpleMapByDbByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			Map<String, Product> productMap=productInfoCacheService.getProductMapByDB(productNos);
			if (CollectionUtils.isEmpty(productMap)) {
				return BaseClientResult.success();
			}
			Map<String, ProductSimple> data=new HashMap<String, ProductSimple>();
			for (Map.Entry<String, Product> item : productMap.entrySet()) {
				data.put(item.getKey(), new ProductSimple(item.getValue()));
			}
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<List<ProductSimple>> getProductSimplListByIds(Set<String> productNos) {
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			List<Product> productList= productInfoCacheService.getProductListByCache(productNos);
			if(CollectionUtils.isEmpty(productList)) {
				return BaseClientResult.success();
			}
			List<ProductSimple> data = new ArrayList<ProductSimple>();
			productList.forEach(item -> {
				data.add(new ProductSimple(item));
			});
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
		
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<List<ProductSimple>> getProductSimplListByDbByIds(Set<String> productNos) {
		
		if (CollectionUtils.isEmpty(productNos)) {
			return BaseClientResult.error();
		}
		try {
			List<Product> productList=productInfoCacheService.getProductListByDB(productNos);
			
			if(CollectionUtils.isEmpty(productList)) {
				return BaseClientResult.success();
			}
			List<ProductSimple> data = new ArrayList<ProductSimple>();
			productList.forEach(item -> {
				data.add(new ProductSimple(item));
			});
			return BaseClientResult.success(data);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
		
	}

	@Override
	public BaseClientResult<Map<String, Sku>> getSkuMapByNos(Set<String> skuNos) {
		return this.getSkuMapByCacheByNos(skuNos);
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, Sku>> getSkuMapByCacheByNos(Set<String> skuNos) {
		if (CollectionUtils.isEmpty(skuNos)) {
			return BaseClientResult.error();
		}
		try {
			Map<String, Sku> sku=productInfoCacheService.getSkuByCache2Map(skuNos);
			return BaseClientResult.success(sku);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	
	}

	@SuppressWarnings("unchecked")
	@Override
	public BaseClientResult<Map<String, Sku>> getSkuMapByDbByNos(Set<String> skuNos) {
		if (CollectionUtils.isEmpty(skuNos)) {
			return BaseClientResult.error();
		}
		try {
			Map<String, Sku> sku=productInfoCacheService.getSkuByDB2Map(skuNos);
			return BaseClientResult.success(sku);
		} catch (Exception e) {
			e.printStackTrace();
			return BaseClientResult.error(e);
		}
	}


	private QueryWrapper<ProductInfo> getQueryWrapper(String companyNo,List<DataQueryRuleItem> items,Integer top){
		QueryModel<ProductInfo> queryModel=new QueryModel<ProductInfo>() {
			@Override
			public QueryWrapper<ProductInfo> customQueryWrapperItem(QueryWrapper<ProductInfo> queryWrapper,DataQueryRuleItem item) {
				return queryWrapper;
			}
		};
		
		QueryWrapper<ProductInfo> queryWrapper=queryModel.getQueryWrapper(
				items, 
				new HashSet<String>(Arrays.asList("tag_values"))
		);
		
		
		queryWrapper = queryWrapper.eq("company_no", companyNo);
		queryWrapper = queryWrapper.eq("is_marketable", YNEnum.YES.getCode());
		
		if(CheckUtils.hasInt(top)) {
			queryWrapper=queryWrapper.last(StrUtil.format("limit 0,{}", top));
		}
		
		
		return queryWrapper;
	}
	

	@Override
	public BaseClientResult<List<Product>> queryProductSimple(@RequestBody ProductQueryRequest request) {
		log.info("+++++++++++++++++++remote queryProductSimple++++++++++++++++++++++++");
		System.out.println("+++++++++++++++++++remote queryProductSimple++++++++++++++++++++++++");
		
		QueryWrapper<ProductInfo> queryWrapper=this.getQueryWrapper(
				request.getCompanyNo(), request.getItems(),request.getTop());
		List<ProductInfo> productList =productInfoService.list(queryWrapper);
		if(CollectionUtils.isEmpty(productList)) {
			return BaseClientResult.success();
		}
		List<Product> data=new ArrayList<Product>();
		productList.forEach(item->{
			data.add(ProductCacheConvertUtils.convertProduct(item,null));
		});
		
		
		if(!CollectionUtils.isEmpty(request.getItems())) {
			for(DataQueryRuleItem item:request.getItems()) {
				if("in".equals(item.getOp()) && "product_no".equals(item.getName()) ) {
					if(!CollectionUtils.isEmpty(item.getVals())) {
						Map<String, Product> prdMap=new HashMap<String, Product>();
						data.forEach(dataItem->{
							prdMap.put(dataItem.getProductNo(), dataItem);
						});
						List<Product> data2=new ArrayList<Product>();
						for(Object _obj:item.getVals()) {
							Product p= prdMap.get(_obj.toString());
							if(p!=null) {
								data2.add(p);
							}
						}
						
						return BaseClientResult.success(data2);
					}
				}
			}
		}
		return BaseClientResult.success(data);
	}

	@Override
	public BaseClientResult<ProductQuery4PageResponse> queryProductSimple4Page(ProductQuery4PageRequest request) {
		QueryWrapper<ProductInfo> queryWrapper=this.getQueryWrapper(
				request.getCompanyNo(), request.getItems(),null);
		IPage<ProductInfo> page =productInfoService.page(new Page<>(request.getPage(), request.getRows()), queryWrapper);
		IPage<Product> data = page.convert(new Function<ProductInfo, Product>() {
			@Override
			public Product apply(ProductInfo entity) {
				return ProductCacheConvertUtils.convertProduct(entity,null);
			}
		});
		
		ProductQuery4PageResponse returnData=new ProductQuery4PageResponse();
		returnData.setPages(data.getPages());
		returnData.setCurrent(data.getCurrent());
		returnData.setSize(data.getSize());
		returnData.setTotal(data.getTotal());
		returnData.setRecords(data.getRecords());
		return BaseClientResult.success(returnData);
	}

}
